package com.lx.idea.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.lx.idea.common.Constant;
import com.lx.idea.common.util.HttpUtil;
import com.lx.idea.common.util.TokenUtil;
import com.lx.idea.mapper.NodeMapper;
import com.lx.idea.model.*;
import com.lx.idea.model.mongodb.MongodbAnalysis;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Author ybb
 * @Description
 * @Date 2021/8/30 14:34
 */
@Service
@Slf4j
public class NodeServiceImpl {

    @Autowired
    NodeMapper nodeMapper;

    @Autowired
    AnalysisServiceImpl analysisService;

    @Autowired
    MongoTemplate mongoTemplate;

    @Autowired
    RedisTemplate redisTemplate;

    @Autowired
    TokenUtil tokenUtil;

    @Autowired
    RestTemplate restTemplate;

    @Value("${ma.tokenUrl}")
    String tokenUrl;

    @Value("${ma.analysisUrl}")
    String analysisUrl;

    @Value("${ma.nodeInfoUrl}")
    String nodeInfoUrl;

    @Value("${ma.analysisPort}")
    String nodePort;



    //获取当前节点
    public CurrentNode getCurrPrefix(){
        return nodeMapper.getCurrPrefix();
    }

    public Node findOne(String nodeName){
        // 这里对应的是数据库的字段
        QueryWrapper<Node> queryWrapper = new QueryWrapper<Node>().eq("node_name",nodeName);
        return  nodeMapper.selectOne(queryWrapper);
    }

    public ApplicationSecret getAppUser(String key, String secret){
        log.info("getAppUser => {}",key,secret);
        return nodeMapper.getAppInfo(key,secret);
    }


    public Object getDocument(HttpServletRequest request,String analysisPath){
        CurrentNode currNode = getCurrPrefix();
        String token = request.getHeader(Constant.token);

        if (analysisPath.startsWith(currNode.getPrefixSelf())){
            if (Constant.level_3 == currNode.getLevel() ){
                return getAnalysisData(analysisPath,token);
            }

            Node nextNode = getNextNode(analysisPath,currNode.getLevel());
            if (ObjectUtils.isEmpty(nextNode)){
                return null;
            }
            //判断下个节点是否为虚拟节点
            if (Constant.virtualType == nextNode.getNodeType()){
                return getAnalysisData(analysisPath,token);
            }
            log.info("转发下级节点解析 {}:{}",nextNode.getNodeIp(),nodePort);
            //转发
            try {

                String nextUrl = "https://"+nextNode.getNodeIp()+":"+nodePort+analysisUrl;
                HttpHeaders headers = new HttpHeaders();
                headers.add("token",token);
                headers.add("token", "123");
                ResponseEntity<String> forEntity = restTemplate.exchange(
                        nextUrl+"/?analysisUrl={analysisUrl}",
                        HttpMethod.GET,
                        new HttpEntity<String>(headers),
                        String.class,
                        analysisPath);
                Object res = null;
                if (!forEntity.getBody().isEmpty() && forEntity.getStatusCodeValue()==200){
                    Map maps=(Map) JSON.parse(forEntity.getBody());
                    res = maps.get("data");
                }

                return res;
            } catch (Exception e) {
                log.info("转发下级节点异常");
                e.printStackTrace();
            }
        }
        return null;
    }

    /*
      获取下一个节点信息
     */
    public Node getNextNode(String analysisPath,int CurrLevel){
        /*
         level 0-1-2-3
         param MA.1.2.3
         当前节点 MA.1.2
         应截取到 Ma.1.2.3
         */
        List arr = Arrays.asList(analysisPath.substring(0,analysisPath.indexOf("/")).split("\\."));
        List ar2 = arr.subList(0,CurrLevel+2);
        String nextPrefix = String.join(".",ar2);
        Node nextNode = nodeMapper.selectJoin(nextPrefix);
        return nextNode;
    }
    /*
      返回解析的数据
      判断数据属性是共有或私有  私有属性需要验证token
     */
    public Object getAnalysisData(String analysisPath,String token){
        AnalysisTb analysisTb = analysisService.getByPath(analysisPath);
        if (null == analysisTb) return null;
        if (Constant.privateAttr == analysisTb.getDataAttr()){
            if (!tokenUtil.verifyToken(token)) return null;
        }
        Query query = Query.query(Criteria.where("analysisPath").is(analysisPath));
        return mongoTemplate.find(query, MongodbAnalysis.class);
    }

    /*
      获取标识 所在注册节点信息
     */
    public Object nodeInfo(String analysisPath,HttpServletRequest request){
        CurrentNode currNode = getCurrPrefix();
        NodeDto nodeDto = new NodeDto();
        nodeDto.setNodeName(currNode.getNodeName());
        nodeDto.setNodeIp(currNode.getNodeIp());
        nodeDto.setNodePort(nodePort);

        if (analysisPath.startsWith(currNode.getPrefixSelf())){
            if (Constant.level_3 == currNode.getLevel() ){
                nodeDto.setNodePort(currNode.getNodePort());
                return nodeDto;
            }
            Node nextNode = getNextNode(analysisPath,currNode.getLevel());
            if (ObjectUtils.isEmpty(nextNode)){
                return null;
            }
            //判断下个节点是否为虚拟节点
            if (Constant.virtualType == nextNode.getNodeType() ){
                if (tokenUtil.verifyToken(request.getHeader(Constant.token))) return null;//token超时
                nodeDto.setNodePort(currNode.getNodePort());
                return nodeDto;
            }
            log.info("转发获取下级节点信息 {}:{}",nextNode.getNodeIp(),nodePort);
            try {
                //转发
                String nextUrl = "https://"+nextNode.getNodeIp()+":"+nodePort+nodeInfoUrl;
                HttpHeaders headers = new HttpHeaders();
                headers.add("token",request.getHeader(Constant.token));
                ResponseEntity<String> forEntity = restTemplate.exchange(
                        nextUrl+"/?analysisUrl={analysisUrl}",
                        HttpMethod.GET,
                        new HttpEntity<String>(headers),
                        String.class,
                        analysisPath);
                Object res = null;
                if (!forEntity.getBody().isEmpty() && forEntity.getStatusCodeValue()==200){
                    Map maps=(Map) JSON.parse(forEntity.getBody());
                    res = maps.get("data");
                }
                return res ;
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }
        }
        return null;
    }

    public Object nextNode(String analysisPath) {
        CurrentNode currNode = getCurrPrefix();

        if (analysisPath.startsWith(currNode.getPrefixSelf())) {
            if (Constant.level_3 == currNode.getLevel()) {
                return currNode;
            }
            Node nextNode = getNextNode(analysisPath, currNode.getLevel());
            if (ObjectUtils.isEmpty(nextNode)) {
                return null;
            }
            //判断下个节点是否为虚拟节点
            if (Constant.virtualType == nextNode.getNodeType()) {
                return currNode;
            }

            NodeDto nodeDto = new NodeDto();
            nodeDto.setNodeName(nextNode.getNodeName());
            nodeDto.setNodeIp(nextNode.getNodeIp());
            nodeDto.setNodePort(nodePort);
            return nodeDto;
        }
        return null;
    }
}
